home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume23 / sps2 / part02 < prev    next >
Encoding:
Internet Message Format  |  1991-01-08  |  53.7 KB

  1. Subject:  v23i048:  SPS, a PS replacement, Part02/04
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 7b9f0d90 1211bb39 9c914368 85893cb6
  5.  
  6. Submitted-by: Robert Ward <olsen!robert@uunet.uu.net>
  7. Posting-number: Volume 23, Issue 48
  8. Archive-name: sps2/part02
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then feed it
  12. # into a shell via "sh file" or similar.  To overwrite existing files,
  13. # type "sh file -c".
  14. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  15. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  16. # Contents:  flagdecode.c flags.h getupage.c globals2.c inittty.c
  17. #   main.c needed.c openfiles.c sps.h stream.c
  18. # Wrapped by rsalz@papaya.bbn.com on Mon Nov 26 14:03:22 1990
  19. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  20. echo If this archive is complete, you will see the following message:
  21. echo '          "shar: End of archive 2 (of 4)."'
  22. if test -f 'flagdecode.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'flagdecode.c'\"
  24. else
  25.   echo shar: Extracting \"'flagdecode.c'\" \(5627 characters\)
  26.   sed "s/^X//" >'flagdecode.c' <<'END_OF_FILE'
  27. X# ifndef lint
  28. Xstatic char SccsId[] =  "@(#)flagdecode.c    1.1\t10/1/88" ;
  29. X# endif
  30. X
  31. X# include       "sps.h"
  32. X# include       "flags.h"
  33. X
  34. X/* FLAGDECODE - Looks at the argument list and sets various internal switches */
  35. Xflagdecode ( argc, argv )
  36. X
  37. Xregister int                    argc ;
  38. Xregister char                   **argv ;
  39. X
  40. X{
  41. X    register char           *chp ;
  42. X    union flaglist          *plist ;
  43. X    union flaglist          *tlist ;
  44. X    union flaglist          *ulist ;
  45. X    static char             usage[] =
  46. X    "sps - Unknown option %s\nUsage - sps [ -dcefgijkoqrsvwyABFNPSTUWZ ][ process|tty|user ] ...\n";
  47. X    union flaglist          *getflgsp() ;
  48. X    extern struct flags     Flg ;
  49. X
  50. X    plist = tlist = ulist = (union flaglist*)0 ;
  51. X    for ( argv++ ; --argc ; argv++ )
  52. X    {
  53. X        chp = *argv ;
  54. X        while ( *chp )
  55. X            switch ( *chp++ )
  56. X            {
  57. X                case '-' :
  58. X                    /* Separation character */
  59. X                    continue ;
  60. X                case 'c' :
  61. X                case 'C' :
  62. X                    /* Print stored command, not args */
  63. X                    Flg.flg_c = 1 ;
  64. X                    continue ;
  65. X                case 'd' :
  66. X                case 'D' :
  67. X                    /* List disc orientated information */
  68. X                    Flg.flg_d = 1 ;
  69. X                    Flg.flg_v = 0 ;
  70. X                    continue ;
  71. X                case 'e' :
  72. X                case 'E' :
  73. X                    /* List environment strings */
  74. X                    Flg.flg_e = 1 ;
  75. X                    continue ;
  76. X                case 'f' :
  77. X                    /* List the father's process id */
  78. X                    Flg.flg_f = 1 ;
  79. X                    continue ;
  80. X                case 'g' :
  81. X                case 'G' :
  82. X                    /* List the process group id */
  83. X                    Flg.flg_g = 1 ;
  84. X                    continue ;
  85. X                case 'i' :
  86. X                case 'I' :
  87. X                    /* Initialise (super-user only) */
  88. X                    Flg.flg_i = 1 ;
  89. X                    continue ;
  90. X                case 'j' :
  91. X                case 'J' :
  92. X                    /* The next argument specifies the
  93. X                       name of the information file */
  94. X                    if ( argc <= 1 )
  95. X                        prexit(
  96. X          "sps - Name of an information file expected after `-j' flag\n" ) ;
  97. X                    argc-- ;
  98. X                    Flg.flg_j = *++argv ;
  99. X                    continue ;
  100. X                case 'k' :
  101. X                case 'K' :
  102. X                    /* Use a disc file such as /vmcore
  103. X                       rather than /dev/{k}mem for
  104. X                       accessing kernel data. The next
  105. X                       argument specifies the file name. */
  106. X                    if ( argc <= 1 )
  107. X                        prexit(
  108. X           "sps - Name of a memory dump file expected after `-k' flag\n" ) ;
  109. X                    argc-- ;
  110. X                    Flg.flg_k = *++argv ;
  111. X                    Flg.flg_o = 1 ;
  112. X                    continue ;
  113. X                case 'l' :
  114. X                case 'v' :
  115. X                case 'L' :
  116. X                case 'V' :
  117. X                    /* Verbose output */
  118. X                    Flg.flg_d = 0 ;
  119. X                    Flg.flg_v = 1 ;
  120. X                    continue ;
  121. X                case 'o' :
  122. X                case 'O' :
  123. X                    /* Avoid looking at the swap device */
  124. X                    Flg.flg_o = 1 ;
  125. X                    continue ;
  126. X                case 'q' :
  127. X                case 'Q' :
  128. X                    /* Show only the user time, not the
  129. X                       user + system times together. */
  130. X                    Flg.flg_q = 1 ;
  131. X                    continue ;
  132. X                case 'r' :
  133. X                case 'R' :
  134. X                    /* Repeat output every n seconds.
  135. X                       The next argument specifies n which
  136. X                       defaults to 5 if omitted. */
  137. X                    Flg.flg_r = 1 ;
  138. X                    if ( argc > 1 )
  139. X                    {
  140. X                        if ( **++argv >= '0'
  141. X                        && **argv <= '9' )
  142. X                        {
  143. X                            argc-- ;
  144. X                            Flg.flg_rdelay
  145. X                                   = atoi( *argv ) ;
  146. X                            continue ;
  147. X                        }
  148. X                        argv-- ;
  149. X                    }
  150. X                    Flg.flg_rdelay = 0 ;
  151. X                    continue ;
  152. X                case 's' :
  153. X                    /* Next argument specifies a symbol
  154. X                       file rather than the default
  155. X                       /vmunix. */
  156. X                    if ( argc <= 1 )
  157. X                        prexit(
  158. X            "sps - Name of a symbol file expected after `-s' flag\n" ) ;
  159. X                    argc-- ;
  160. X                    Flg.flg_s = *++argv ;
  161. X                    continue ;
  162. X                case 'w' :
  163. X                    /* Wide output, exceeding 79 columns */
  164. X                    Flg.flg_w = 1 ;
  165. X                    continue ;
  166. X                case 'y' :
  167. X                case 'Y' :
  168. X                    /* List current tty information */
  169. X                    Flg.flg_y = 1 ;
  170. X                    continue ;
  171. X                case 'a' :
  172. X                case 'A' :
  173. X                    /* List all processes */
  174. X                    Flg.flg_AZ = 1 ;
  175. X                    Flg.flg_A = 1 ;
  176. X                    continue ;
  177. X                case 'b' :
  178. X                case 'B' :
  179. X                    /* List only busy processes */
  180. X                    Flg.flg_AZ = 1 ;
  181. X                    Flg.flg_B = 1 ;
  182. X                    continue ;
  183. X                case 'F' :
  184. X                    /* List only foreground processes */
  185. X                    Flg.flg_AZ = 1 ;
  186. X                    Flg.flg_F = 1 ;
  187. X                    continue ;
  188. X                case 'n' :
  189. X                case 'N' :
  190. X                    /* No processes, just the summary line*/
  191. X                    Flg.flg_AZ = 1 ;
  192. X                    Flg.flg_N = 1 ;
  193. X                    continue ;
  194. X                case 'p' :
  195. X                case 'P' :
  196. X                    /* List only the given process ids */
  197. X                    Flg.flg_AZ = 1 ;
  198. X                    Flg.flg_P = 1 ;
  199. X                    if ( !plist )
  200. X                       plist=Flg.flg_Plist=getflgsp( argc );
  201. X                    while ( argc > 1 )
  202. X                    {
  203. X                        if ( **++argv == '-' )
  204. X                        {
  205. X                            --argv ;
  206. X                            break ;
  207. X                        }
  208. X                        --argc ;
  209. X                        plist->f_chp = *argv ;
  210. X                        (++plist)->f_chp = (char*)0 ;
  211. X                    }
  212. X                    continue ;
  213. X                case 'S' :
  214. X                    /* List only stopped processes */
  215. X                    Flg.flg_AZ = 1 ;
  216. X                    Flg.flg_S = 1 ;
  217. X                    continue ;
  218. X                case 't' :
  219. X                case 'T' :
  220. X                    /* List only processes attached to the
  221. X                       specified terminals */
  222. X                    Flg.flg_AZ = 1 ;
  223. X                    Flg.flg_T = 1 ;
  224. X                    if ( !tlist )
  225. X                       tlist=Flg.flg_Tlist=getflgsp( argc );
  226. X                    while ( argc > 1 )
  227. X                    {
  228. X                        if ( **++argv == '-' )
  229. X                        {
  230. X                            --argv ;
  231. X                            break ;
  232. X                        }
  233. X                        --argc ;
  234. X                        tlist->f_chp = *argv ;
  235. X                        (++tlist)->f_chp = (char*)0 ;
  236. X                    }
  237. X                    continue ;
  238. X                case 'u' :
  239. X                case 'U' :
  240. X                    /* List only processes belonging to the
  241. X                       specified users */
  242. X                    Flg.flg_AZ = 1 ;
  243. X                    Flg.flg_U = 1 ;
  244. X                    if ( !ulist )
  245. X                       ulist=Flg.flg_Ulist=getflgsp( argc );
  246. X                    while ( argc > 1 )
  247. X                    {
  248. X                        if ( **++argv == '-' )
  249. X                        {
  250. X                            --argv ;
  251. X                            break ;
  252. X                        }
  253. X                        --argc ;
  254. X                        ulist->f_chp = *argv ;
  255. X                        (++ulist)->f_chp = (char*)0 ;
  256. X                    }
  257. X                    continue ;
  258. X                case 'W' :
  259. X                    /* List only waiting processes */
  260. X                    Flg.flg_AZ = 1 ;
  261. X                    Flg.flg_W = 1 ;
  262. X                    continue ;
  263. X                case 'z' :
  264. X                case 'Z' :
  265. X                    /* List only zombie processes */
  266. X                    Flg.flg_AZ = 1 ;
  267. X                    Flg.flg_Z = 1 ;
  268. X                    continue ;
  269. X                default :
  270. X                    prexit( usage, *argv ) ;
  271. X                    /* NOTREACHED */
  272. X            }
  273. X    }
  274. X}
  275. END_OF_FILE
  276.   if test 5627 -ne `wc -c <'flagdecode.c'`; then
  277.     echo shar: \"'flagdecode.c'\" unpacked with wrong size!
  278.   fi
  279.   # end of 'flagdecode.c'
  280. fi
  281. if test -f 'flags.h' -a "${1}" != "-c" ; then 
  282.   echo shar: Will not clobber existing file \"'flags.h'\"
  283. else
  284.   echo shar: Extracting \"'flags.h'\" \(2638 characters\)
  285.   sed "s/^X//" >'flags.h' <<'END_OF_FILE'
  286. X# ifndef lint
  287. Xstatic char FlagsHId[] =  "@(#)flags.h    1.1\t10/1/88" ;
  288. X# endif
  289. X
  290. X/* Structure holding information specified in the option list ... */
  291. Xunion flaglist
  292. X{
  293. X    char                    *f_chp ;        /* Option specified as string */
  294. X    int                     f_uid ;         /* Numerical user id */
  295. X    int                     f_pid ;         /* Numerical process id */
  296. X    struct ttyline          *f_ttyline ;    /* Specified tty */
  297. X} ;
  298. X
  299. X/* Structure holding global information specifed by arg list options ... */
  300. Xstruct flags
  301. X{
  302. X    int                     flg_c:1 ;       /* print command from upage */
  303. X    int                     flg_d:1 ;       /* disc orientated output */
  304. X    int                     flg_e:1 ;       /* print environment string */
  305. X    int                     flg_f:1 ;       /* print process father # */
  306. X    int                     flg_g:1 ;       /* print process group # */
  307. X    int                     flg_i:1 ;       /* initialise sps */
  308. X    char                    *flg_j ;        /* Use this as the info file */
  309. X    char                    *flg_k ;        /* Use this as the {k}mem file*/
  310. X    int                     flg_o:1 ;       /* avoid the swap device */
  311. X    int                     flg_q:1 ;       /* show user time only */
  312. X    int                     flg_r:1 ;       /* repeat output */
  313. X    unsigned                flg_rdelay ;    /* ... with this much delay */
  314. X    char                    *flg_s ;        /* Use this as the symbol file*/
  315. X    int                     flg_v:1 ;       /* print verbose listing */
  316. X    int                     flg_w:1 ;       /* print wide output */
  317. X    int                     flg_y:1 ;       /* print tty information */
  318. X    int                     flg_A:1 ;       /* print all processes */
  319. X    int                     flg_B:1 ;       /* print busy processes */
  320. X    int                     flg_F:1 ;       /* print foreground processes */
  321. X    int                     flg_N:1 ;       /* print no processes */
  322. X    int                     flg_P:1 ;       /* print specified process #'s*/
  323. X    int                     flg_S:1 ;       /* print stopped processes */
  324. X    int                     flg_T:1 ;       /* print procs for given ttys */
  325. X    int                     flg_U:1 ;       /* print procs for given users*/
  326. X    int                     flg_W:1 ;       /* print waiting processes */
  327. X    int                     flg_Z:1 ;       /* print zombie processes */
  328. X    int                     flg_AZ:1 ;      /* One of A to Z was specified*/
  329. X    union flaglist          *flg_Plist ;    /* List of specified processes*/
  330. X    union flaglist          *flg_Tlist ;    /* List of specified ttys */
  331. X    union flaglist          *flg_Ulist ;    /* List of specified users */
  332. X} ;
  333. END_OF_FILE
  334.   if test 2638 -ne `wc -c <'flags.h'`; then
  335.     echo shar: \"'flags.h'\" unpacked with wrong size!
  336.   fi
  337.   # end of 'flags.h'
  338. fi
  339. if test -f 'getupage.c' -a "${1}" != "-c" ; then 
  340.   echo shar: Will not clobber existing file \"'getupage.c'\"
  341. else
  342.   echo shar: Extracting \"'getupage.c'\" \(4161 characters\)
  343.   sed "s/^X//" >'getupage.c' <<'END_OF_FILE'
  344. X# ifndef lint
  345. Xstatic char SccsId[] =  "@(#)getupage.c    1.3\t8/2/90" ;
  346. X# endif
  347. X
  348. X# include       "sps.h"
  349. X# ifdef KVM
  350. X#  include      <kvm.h>
  351. X# else
  352. X#  include      <h/vm.h>
  353. X#  ifdef BSD42
  354. X#  include    <machine/pte.h>
  355. X#  else
  356. X#  include      <h/pte.h>
  357. X#  endif
  358. X# endif
  359. X# include       <stdio.h>
  360. X
  361. X/*
  362. X** GETUPAGE - Reads the upage for the specified process as well as sufficient
  363. X** page tables entries for reading the command arguments. The pte's are read
  364. X** into the argument `ptetbl'. The upage is read into the external variable
  365. X** `User'. This procedure returns 1 if the upage was successfully read.
  366. X*/
  367. X
  368. X# ifndef KVM
  369. X
  370. X# define        usrpt           (Info.i_usrpt)
  371. X
  372. Xgetupage ( p, ptetbl )
  373. X
  374. Xregister struct process         *p ;
  375. Xregister struct pte             *ptetbl ;
  376. X
  377. X{
  378. X    register int            i ;
  379. X    register int            ncl ;
  380. X    struct pte              pte ;
  381. X    extern struct info      Info ;
  382. X    extern union userstate  User ;
  383. X    extern int              Flmem, Flkmem, Flswap ;
  384. X
  385. X    /* If the process is not loaded, look for the upage on the swap device*/
  386. X    if ( !(p->pr_p.p_flag & SLOAD) )
  387. X    {                               
  388. X# ifdef BSD42
  389. X        swseek( (long)dtob( p->pr_p.p_swaddr ) ) ;
  390. X# else BSD42
  391. X        swseek( (long)ctob( p->pr_p.p_swaddr ) ) ;
  392. X# endif BSD42
  393. X# ifdef SUN
  394. X        if ( read( Flswap, (char*)&User.u_us, sizeof( union userstate ))
  395. X        != sizeof( union userstate ) )
  396. X# else SUN
  397. X        if ( read( Flswap, (char*)&User.u_us, sizeof( struct user ) )
  398. X        != sizeof( struct user ) )
  399. X# endif SUN
  400. X        {
  401. X            fprintf( stderr,
  402. X                "sps - Can't read upage of process %d\n",
  403. X                p->pr_p.p_pid ) ;
  404. X            return ( 0 ) ;
  405. X        }
  406. X        return ( 1 ) ;          
  407. X    }                               
  408. X    /* The process is loaded. Locate the process pte's by reading
  409. X       the pte of their base address from system virtual address space. */
  410. X# ifdef DEC3100
  411. X    /* This method of accessing the upage suffices on the DEC Station
  412. X       but only provides sufficient pte's to read the upage, leaving the
  413. X       command arguments inaccessible. */
  414. X    memseek( Flkmem, (long)p->pr_p.p_addr ) ;
  415. X    if ( read( Flkmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
  416. X    != (UPAGES+CLSIZE)*sizeof( struct pte ) )
  417. X    {
  418. X        fprintf( stderr, "sps - Can't read page table of process %d\n",
  419. X            p->pr_p.p_pid ) ;
  420. X        return ( 0 ) ;
  421. X    }
  422. X# else DEC3100
  423. X    memseek( Flkmem, (long)&Info.i_usrptmap[ btokmx(p->pr_p.p_p0br)
  424. X        + p->pr_p.p_szpt-1 ] ) ;
  425. X    if ( read( Flkmem, (char*)&pte, sizeof( struct pte ) )
  426. X    != sizeof( struct pte ) )
  427. X    {
  428. X        fprintf( stderr,
  429. X              "sps - Can't read indir pte for upage of process %d\n",
  430. X            p->pr_p.p_pid ) ;
  431. X        return ( 0 ) ;
  432. X    }                               
  433. X    /* Now read the process' pte's from physical memory. We need to access
  434. X       sufficient pte's for the upage and for the command arguments. */
  435. X    memseek( Flmem, (long)ctob( pte.pg_pfnum+1 )
  436. X        - (UPAGES+CLSIZE)*sizeof( struct pte ) ) ;
  437. X    if ( read( Flmem, (char*)ptetbl, (UPAGES+CLSIZE)*sizeof( struct pte ) )
  438. X    != (UPAGES+CLSIZE)*sizeof( struct pte ) )
  439. X    {
  440. X        fprintf( stderr, "sps - Can't read page table of process %d\n",
  441. X            p->pr_p.p_pid ) ;
  442. X        return ( 0 ) ;
  443. X    }
  444. X# endif DEC3100
  445. X    /* Now we can read the pages belonging to the upage.
  446. X       Here we read in an entire click at one go. */
  447. X    ncl = (sizeof( struct user ) + NBPG*CLSIZE - 1) / (NBPG*CLSIZE) ;
  448. X    while ( --ncl >= 0 )            
  449. X    {                               
  450. X        i = ncl * CLSIZE ;
  451. X# ifdef DEC3100
  452. X        memseek( Flmem, (long)ctob( ptetbl[ i ].pg_pfnum ) ) ;
  453. X# else DEC3100
  454. X        memseek( Flmem, (long)ctob( ptetbl[ CLSIZE+i ].pg_pfnum ) ) ;
  455. X# endif DEC3100
  456. X        if ( read( Flmem, User.u_pg[i], CLSIZE*NBPG ) != CLSIZE*NBPG )
  457. X        {
  458. X            fprintf( stderr,
  459. X                "sps - Can't read page 0x%x of process %d\n",
  460. X                ptetbl[ CLSIZE+i ].pg_pfnum, p->pr_p.p_pid ) ;
  461. X            return ( 0 ) ;
  462. X        }
  463. X    }
  464. X    return ( 1 ) ;
  465. X}
  466. X
  467. X# else KVM
  468. X
  469. Xgetupage ( p )
  470. X
  471. Xregister struct process         *p ;
  472. X
  473. X{
  474. X        struct user            *upage ;
  475. X    extern union userstate  User ;
  476. X    extern kvm_t           *Flkvm ;
  477. X
  478. X    if (upage = kvm_getu( Flkvm, &p->pr_p ) )
  479. X    {
  480. X            bcopy( (char *)upage, User.u_pg[0], sizeof( struct user ) ) ;
  481. X        return ( 1 ) ;
  482. X    }
  483. X    fprintf( stderr, "sps - Can't read upage of process %d\n",
  484. X        p->pr_p.p_pid ) ;
  485. X    return ( 0 ) ;
  486. X}
  487. X
  488. X# endif KVM
  489. END_OF_FILE
  490.   if test 4161 -ne `wc -c <'getupage.c'`; then
  491.     echo shar: \"'getupage.c'\" unpacked with wrong size!
  492.   fi
  493.   # end of 'getupage.c'
  494. fi
  495. if test -f 'globals2.c' -a "${1}" != "-c" ; then 
  496.   echo shar: Will not clobber existing file \"'globals2.c'\"
  497. else
  498.   echo shar: Extracting \"'globals2.c'\" \(6807 characters\)
  499.   sed "s/^X//" >'globals2.c' <<'END_OF_FILE'
  500. X# ifndef lint
  501. Xstatic char SccsId[] =  "@(#)globals2.c    1.2\t7/4/90" ;
  502. X# endif
  503. X
  504. X# include       "sps.h"
  505. X
  506. X/* Read Only variables, global to the code of sps ... */
  507. X
  508. X/* Null ttyline device ... */
  509. Xstruct ttyline                  Notty = { "  " } ;
  510. X
  511. X/*
  512. X** The symbol table. For each address read from the kernel during
  513. X** initialisation, this table shows the following:
  514. X**      i.   the name of that symbol within the kernel ;
  515. X**      ii.  whether an extra indirection is needed through the kernel,
  516. X**           i.e. whether the value of that symbol should be obtained
  517. X**           rather than its address.
  518. X**      iii. where the obtained value/address is placed in the Info structure ;
  519. X**      iv.  whether the obtained value is associated with a reason for
  520. X**           a process wait state.
  521. X*/
  522. X/* The order of entries in this table is unimportant. */
  523. X
  524. Xextern struct info              Info ;
  525. X
  526. Xstruct symbol   Symbollist[] =
  527. X{       
  528. X    /* Kernel addresses required in order to access process,
  529. X       tty and upage information. All these addresses should be
  530. X       located in the symbol file during initialisation. */
  531. X    { "_proc",      1,  (caddr_t*)&Info.i_proc0,    (char*)0        },
  532. X    { "_nproc",     1,  (caddr_t*)&Info.i_nproc,    (char*)0        },
  533. X# ifdef ULTRIX20
  534. X    { "_gnode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
  535. X    { "_ngnode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
  536. X# else
  537. X#  ifndef SUNOS41
  538. X    { "_inode",     1,  (caddr_t*)&Info.i_inode0,   (char*)0        },
  539. X#  endif SUNOS41
  540. X    { "_ninode",    1,  (caddr_t*)&Info.i_ninode,   (char*)0        },
  541. X# endif ULTRIX20
  542. X
  543. X# ifndef SUNOS40
  544. X    { "_text",      1,  (caddr_t*)&Info.i_text0,    (char*)0        },
  545. X    { "_ntext",     1,  (caddr_t*)&Info.i_ntext,    (char*)0        },
  546. X    { "_swbuf",     1,  (caddr_t*)&Info.i_swbuf0,   (char*)0        },
  547. X    { "_nswbuf",    1,  (caddr_t*)&Info.i_nswbuf,   (char*)0        },
  548. X    { "_buf",       1,  (caddr_t*)&Info.i_buf0,     (char*)0        },
  549. X    { "_nbuf",      1,  (caddr_t*)&Info.i_nbuf,     (char*)0        },
  550. X    { "_ecmx",      1,  (caddr_t*)&Info.i_ecmx,     (char*)0        },
  551. X    { "_Usrptmap",  0,  (caddr_t*)&Info.i_usrptmap, (char*)0        },
  552. X    { "_usrpt",     0,  (caddr_t*)&Info.i_usrpt,    (char*)0        },
  553. X    { "_dmmin",     1,  (caddr_t*)&Info.i_dmmin,    (char*)0        },
  554. X    { "_dmmax",     1,  (caddr_t*)&Info.i_dmmax,    (char*)0        },
  555. X# endif SUNOS40
  556. X
  557. X    { "_cdevsw",    0,  (caddr_t*)&Info.i_cdevsw,   (char*)0        },
  558. X# ifdef BSD42
  559. X#  ifdef NFS
  560. X#   ifndef NOQUOTA
  561. X    { "_dquot",     1,  (caddr_t*)&Info.i_quota0,   (char*)0        },
  562. X    { "_ndquot",    1,  (caddr_t*)&Info.i_nquota,   (char*)0        },
  563. X#   endif NOQUOTA
  564. X#  else NFS
  565. X    { "_quota",     1,  (caddr_t*)&Info.i_quota0,   (char*)0        },
  566. X    { "_nquota",    1,  (caddr_t*)&Info.i_nquota,   (char*)0        },
  567. X#  endif NFS
  568. X    { "_mbutl",     0,  (caddr_t*)&Info.i_mbutl,    (char*)0        },
  569. X# else BSD42
  570. X    { "_hz",        1,  (caddr_t*)&Info.i_hz,       (char*)0        },
  571. X# endif BSD42
  572. X
  573. X# ifdef CHAOS
  574. X    { "_Chconntab", 0,  &Info.i_Chconntab,          (char*)0        },
  575. X# endif CHAOS
  576. X
  577. X# ifdef SUNOS40
  578. X    { "_maxmem",    1,  (caddr_t*)&Info.i_ecmx,    (char*)0    },
  579. X    { "_segvn_ops",    0,  (caddr_t*)&Info.i_segvn_ops,(char*)0    },
  580. X    { "_pty_softc",    0,  (caddr_t*)&Info.i_ptybase,    (char*)0    },
  581. X    { "_npty",    1,  (caddr_t*)&Info.i_npty,    (char*)0    },
  582. X#  ifdef SUNOS41
  583. X    { "_strst",    0,  (caddr_t*)&Info.i_strst,    (char*)0    },
  584. X    { "_allstream",    1,  (caddr_t*)&Info.i_allstream, (char*)0    },
  585. X#  else SUNOS41
  586. X    { "_streams",    0,  (caddr_t*)&Info.i_streams,    (char*)0    },
  587. X    { "_streamsNSTREAMS", 1, (caddr_t*)&Info.i_streamsNSTREAMS ,(char*)0 },
  588. X#  endif SUNOS41
  589. X    { "_Sysbase",    1,  (caddr_t*)&Info.i_sysbase,    (char*)0    },
  590. X# endif SUNOS40
  591. X
  592. X    /* Kernel addresses associated with process wait states.
  593. X       It is not important if some of these addresses are unresolved
  594. X       at initialisation. */
  595. X# ifndef SUN
  596. X    { "_fltab",     0,  &Info.i_waitstate[0],       "floppy"        },
  597. X    { "_tu",        0,  &Info.i_waitstate[1],       "tu58"          },
  598. X    { "_lp_softc",  0,  &Info.i_waitstate[3],       "printr"        },
  599. X# endif SUN
  600. X    { "_bfreelist", 0,  &Info.i_waitstate[2],       "buffer"        },
  601. X    { "_lbolt",     0,  &Info.i_waitstate[4],       "lbolt"         },
  602. X    { "_runin",     0,  &Info.i_waitstate[5],       "runin"         },
  603. X    { "_runout",    0,  &Info.i_waitstate[6],       "runout"        },
  604. X    { "_ipc",       0,  &Info.i_waitstate[7],       "ptrace"        },
  605. X# ifdef SUNOS41
  606. X    { "_uunix",     0,  &Info.i_waitstate[8],       "pause"         },
  607. X# else SUNOS41
  608. X    { "_u",         0,  &Info.i_waitstate[8],       "pause"         },
  609. X# endif SUNOS41
  610. X    { "_freemem",   0,  &Info.i_waitstate[9],       "freemm"        },
  611. X    { "_kernelmap", 0,  &Info.i_waitstate[10],      "kermap"        },
  612. X    { "_cwaiting",  0,  &Info.i_waitstate[11],      "cwait"         },
  613. X# ifdef BSD42
  614. X    { "_selwait",   0,  &Info.i_waitstate[12],      "select"        },
  615. X# endif BSD42
  616. X# ifdef CHAOS
  617. X    { "_Chrfclist", 0,  &Info.i_waitstate[13],      "chrfc"         },
  618. X# endif CHAOS
  619. X# ifndef SUN
  620. X    { "_rhpbuf",    0,  &Info.i_waitstate[14],      "rhpbuf"        },
  621. X    { "_rhtbuf",    0,  &Info.i_waitstate[15],      "rhtbuf"        },
  622. X    { "_ridcbuf",   0,  &Info.i_waitstate[16],      "ridcbf"        },
  623. X    { "_rikbuf",    0,  &Info.i_waitstate[17],      "rikbuf"        },
  624. X    { "_rmtbuf",    0,  &Info.i_waitstate[18],      "rmtbuf"        },
  625. X    { "_rrkbuf",    0,  &Info.i_waitstate[19],      "rrkbuf"        },
  626. X    { "_rrlbuf",    0,  &Info.i_waitstate[20],      "rrlbuf"        },
  627. X    { "_rrxbuf",    0,  &Info.i_waitstate[21],      "rrxbuf"        },
  628. X    { "_rswbuf",    0,  &Info.i_waitstate[22],      "rswbuf"        },
  629. X    { "_rtmbuf",    0,  &Info.i_waitstate[23],      "rtmbuf"        },
  630. X    { "_rtsbuf",    0,  &Info.i_waitstate[24],      "rtsbuf"        },
  631. X    { "_rudbuf",    0,  &Info.i_waitstate[25],      "rudbuf"        },
  632. X    { "_rupbuf",    0,  &Info.i_waitstate[26],      "rupbuf"        },
  633. X    { "_rutbuf",    0,  &Info.i_waitstate[27],      "rutbuf"        },
  634. X    { "_rvabuf",    0,  &Info.i_waitstate[28],      "rvabuf"        },
  635. X    { "_rvpbuf",    0,  &Info.i_waitstate[29],      "rvpbuf"        },
  636. X    { "_chtbuf",    0,  &Info.i_waitstate[30],      "chtbuf"        },
  637. X    { "_cmtbuf",    0,  &Info.i_waitstate[31],      "cmtbuf"        },
  638. X    { "_ctmbuf",    0,  &Info.i_waitstate[32],      "ctmbuf"        },
  639. X    { "_ctsbuf",    0,  &Info.i_waitstate[33],      "ctsbuf"        },
  640. X    { "_cutbuf",    0,  &Info.i_waitstate[34],      "cutbuf"        },
  641. X#  ifdef NFS
  642. X    { "_async_bufhead", 0,  &Info.i_waitstate[35],  "async"        },
  643. X#  endif NFS
  644. X# else SUN
  645. X    { "_async_bufhead", 0,  &Info.i_waitstate[14],  "async"        },
  646. X    { "_desktops",    0,  &Info.i_waitstate[15],    "dtops"        },
  647. X# endif SUN
  648. X# ifdef ULTRIX20
  649. X    { "_async_bufhead", 0,  &Info.i_waitstate[35],  "async"        },
  650. X# endif ULTRIX20
  651. X    { (char*)0,     0,  (caddr_t*)0,                (char*)0        }
  652. X} ;
  653. END_OF_FILE
  654.   if test 6807 -ne `wc -c <'globals2.c'`; then
  655.     echo shar: \"'globals2.c'\" unpacked with wrong size!
  656.   fi
  657.   # end of 'globals2.c'
  658. fi
  659. if test -f 'inittty.c' -a "${1}" != "-c" ; then 
  660.   echo shar: Will not clobber existing file \"'inittty.c'\"
  661. else
  662.   echo shar: Extracting \"'inittty.c'\" \(3716 characters\)
  663.   sed "s/^X//" >'inittty.c' <<'END_OF_FILE'
  664. X# ifndef lint
  665. Xstatic char SccsId[] =  "@(#)inittty.c    1.1\t10/1/88" ;
  666. X# endif
  667. X
  668. X# include       "sps.h"
  669. X# include       <h/conf.h>
  670. X# include       <h/ioctl.h>
  671. X# ifdef SUNOS40
  672. X# include       <h/stream.h>
  673. X# else
  674. X# include       <h/tty.h>
  675. X# endif
  676. X# include       <sys/stat.h>
  677. X# include       <stdio.h>
  678. X
  679. X/* INITTTY - Initialise the tty part of the info structure */
  680. Xinittty ()
  681. X{
  682. X    register struct ttyline *lp ;
  683. X# ifdef BSD42
  684. X    register struct direct  *dp ;
  685. X    DIR                     *dfd ;
  686. X# else
  687. X    struct direct           dir ;
  688. X    FILE                    *dfd ;
  689. X# endif
  690. X    struct stat             statbuf ;
  691. X    static char             filedev[] = FILE_DEV ;
  692. X    extern struct info      Info ;
  693. X# ifdef BSD42
  694. X    DIR                     *opendir() ;
  695. X    struct direct           *readdir() ;
  696. X# else
  697. X    FILE                    *fopen() ;
  698. X# endif
  699. X
  700. X    lp = Info.i_ttyline ;
  701. X# ifdef BSD42
  702. X    if ( !(dfd = opendir( filedev )) )
  703. X# else
  704. X    if ( !(dfd = fopen( filedev, "r" )) )
  705. X# endif
  706. X        prexit( "Can't open %s\n", filedev ) ;
  707. X    if ( chdir( filedev ) < 0 )
  708. X        prexit( "sps - Can't chdir to %s\n", filedev ) ;
  709. X# ifdef BSD42
  710. X    /* Read all entries in the device directory, looking for ttys */
  711. X    while ( dp = readdir( dfd ) )
  712. X    {       /* Skip entries that do not match "tty" or "console" */
  713. X        if ( strncmp( "tty", dp->d_name, 3 )
  714. X        &&   strcmp( "console", dp->d_name ) )
  715. X            continue ;
  716. X        /* Skip "tty" itself */
  717. X        if ( dp->d_namlen == 3 )
  718. X            continue ;
  719. X# ifdef CHAOS
  720. X        /* Skip chaos ttys ; they are accessed during ttystatus() */
  721. X        if ( dp->d_namelen > 3 &&
  722. X        dp->d_name[ sizeof( "tty" ) - 1 ] == 'C' )
  723. X            continue ;
  724. X# endif
  725. X        if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
  726. X            prexit( "sps - Too many ttys in %s\n", filedev ) ;
  727. X        /* Copy the tty name into the information entry */
  728. X        if ( !strcmp( dp->d_name, "console" ) )
  729. X        {
  730. X            lp->l_name[0] = 'c' ;
  731. X            lp->l_name[1] = 'o' ;
  732. X        }
  733. X        else
  734. X        {
  735. X            lp->l_name[0] = dp->d_name[3] ;
  736. X            lp->l_name[1] = dp->d_name[4] ;
  737. X        }
  738. X        /* Ensure that this tty is actually a valid character device */
  739. X        if ( stat( dp->d_name, &statbuf ) < 0 )
  740. X            continue ;
  741. X# else
  742. X    /* Read all entries in the device directory, looking for ttys */
  743. X    while ( fread( (char*)&dir, sizeof( struct direct ), 1, dfd ) == 1 )
  744. X    {       /* Skip entries that do not match "tty" or "console" */
  745. X        if ( strncmp( "tty", dir.d_name, 3 )
  746. X        &&   strcmp( "console", dir.d_name ) )
  747. X            continue ;
  748. X        /* Skip "tty" itself */
  749. X        if ( dir.d_name[3] == '\0' )
  750. X            continue ;
  751. X# ifdef CHAOS
  752. X        /* Skip chaos ttys ; they are accessed during ttystatus() */
  753. X        if ( dir.d_name[ sizeof( "tty" ) - 1 ] == 'C' )
  754. X            continue ;
  755. X# endif
  756. X        if ( lp >= &Info.i_ttyline[ MAXTTYS ] )
  757. X            prexit( "sps - Too many ttys in %s\n", filedev ) ;
  758. X        /* Copy the tty name into the information entry */
  759. X        if ( !strcmp( dir.d_name, "console" ) )
  760. X        {
  761. X            lp->l_name[0] = 'c' ;
  762. X            lp->l_name[1] = 'o' ;
  763. X        }
  764. X        else
  765. X        {
  766. X            lp->l_name[0] = dir.d_name[3] ;
  767. X            lp->l_name[1] = dir.d_name[4] ;
  768. X        }
  769. X        /* Ensure that this tty is actually a valid character device */
  770. X        if ( stat( dir.d_name, &statbuf ) < 0 )
  771. X            continue ;
  772. X# endif
  773. X        if ( (statbuf.st_mode & S_IFMT) != S_IFCHR )
  774. X            continue ;
  775. X        /* Find the device # of the tty and the address of its
  776. X           associated struct tty in /dev/kmem. */
  777. X        lp->l_dev = statbuf.st_rdev ;
  778. X        if ( getkmem ( (long)&Info.i_cdevsw[ major( statbuf.st_rdev ) ]
  779. X# ifdef SUNOS40
  780. X            .d_str,
  781. X# else
  782. X            .d_ttys,
  783. X# endif
  784. X        (char*)&lp->l_addr, sizeof( lp->l_addr ) )
  785. X        != sizeof( lp->l_addr ) )
  786. X        {
  787. X            fprintf( stderr, "sps - Can't read struct tty for %s\n",
  788. X# ifdef BSD42
  789. X                dp->d_name ) ;
  790. X# else
  791. X                dir.d_name ) ;
  792. X# endif
  793. X            continue ;
  794. X        }
  795. X# ifndef SUNOS40
  796. X        lp->l_addr += (int)minor( statbuf.st_rdev ) ;
  797. X# endif
  798. X        lp++ ;
  799. X    }
  800. X# ifdef BSD42
  801. X    (void)closedir( dfd ) ;
  802. X# else
  803. X    (void)fclose( dfd ) ;
  804. X# endif
  805. X}
  806. END_OF_FILE
  807.   if test 3716 -ne `wc -c <'inittty.c'`; then
  808.     echo shar: \"'inittty.c'\" unpacked with wrong size!
  809.   fi
  810.   # end of 'inittty.c'
  811. fi
  812. if test -f 'main.c' -a "${1}" != "-c" ; then 
  813.   echo shar: Will not clobber existing file \"'main.c'\"
  814. else
  815.   echo shar: Extracting \"'main.c'\" \(4246 characters\)
  816.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  817. X# ifndef lint
  818. Xstatic char SccsId[] =  "@(#)main.c    1.1\t10/1/88" ;
  819. X# endif
  820. X
  821. X# include       "sps.h"
  822. X# include       "flags.h"
  823. X# ifdef KVM
  824. X# include       <kvm.h>
  825. X# include       <fcntl.h>
  826. X# endif KVM
  827. X# ifndef SUNOS40
  828. X# include       <h/text.h>
  829. X# endif
  830. X# include       <sys/stat.h>
  831. X# include       <stdio.h>
  832. X
  833. X
  834. X/* SPS - Show Process Status */
  835. X
  836. X/* J. R. Ward - Hasler AG, Bern, Switzerland         - 24 May 1985 */
  837. X/*                                  - 26 Nov 1986 */
  838. X/* J. R. Ward - Olsen & Associates, Zuerich, Switzerland -  1 Oct 1988 */
  839. X/* <robert@olsen.uucp> */
  840. X
  841. X/* NFS additions and SunOS4.0 support by Alexander Dupuy
  842. X   <dupuy@ncs.columbia.edu> and Charlie Kim <cck@cunixc.cc.columbia.edu>.
  843. X   Ultrix 2.x support by Rob Lehman at CUCCA. */
  844. X
  845. Xmain ( argc,argv )
  846. X
  847. Xint                             argc ;
  848. Xchar                            **argv ;
  849. X
  850. X{
  851. X    register struct process *plist ;
  852. X    register struct process *process ;
  853. X# ifndef SUNOS40
  854. X    register struct text    *text ;
  855. X# endif
  856. X    int                     flinfo ;
  857. X    char            *fileinfo, *filesymbol ;
  858. X    struct stat        sinfo, ssymbol ;
  859. X# ifdef WARNPASSWD
  860. X    struct stat        spasswd ;
  861. X# endif
  862. X    extern struct flags     Flg ;
  863. X    extern struct info      Info ;
  864. X# ifdef KVM
  865. X    extern kvm_t           *Flkvm ;
  866. X# else
  867. X    extern int              Flmem ;
  868. X    extern int              Flkmem ;
  869. X    extern int              Flswap ;
  870. X# endif
  871. X    char                    *getcore() ;
  872. X    struct process          *needed(), *mktree() ;
  873. X
  874. X    /* Renice as fast as possible for root only (Suggested by Jeff Mogul,
  875. X       gregorio!mogul) */
  876. X    if ( !getuid() )
  877. X        (void)nice( -40 ) ;
  878. X    /* Decode the flag arguments */
  879. X    flagdecode( argc, argv ) ;      
  880. X    /* Determine the terminal width */
  881. X    if ( !Flg.flg_w && !Flg.flg_N && !Flg.flg_i )
  882. X        termwidth() ;
  883. X    /* Open the cpu physical memory, kernel virtual memory and swap device*/
  884. X# ifdef KVM
  885. X    Flkvm = kvm_open( Flg.flg_s, Flg.flg_k, NULL, O_RDONLY, "sps" ) ;
  886. X# else
  887. X    if ( Flg.flg_k )
  888. X    {
  889. X        Flmem = openfile( Flg.flg_k ) ;
  890. X        Flkmem = Flmem ;
  891. X    }
  892. X    else
  893. X    {
  894. X        Flmem = openfile( FILE_MEM ) ;
  895. X        Flkmem = openfile( FILE_KMEM ) ;
  896. X        if ( !Flg.flg_o )
  897. X            Flswap = openfile( FILE_SWAP ) ;
  898. X    }
  899. X# endif
  900. X    if ( Flg.flg_i )
  901. X    {       /* -i flag for info file initialisation */
  902. X        initialise() ;          
  903. X        exit( 0 ) ;
  904. X    }
  905. X    /* Check that the information file is newer than the symbol and
  906. X       password files, suggested by gregorio!mogul */
  907. X    fileinfo = Flg.flg_j ? Flg.flg_j : FILE_INFO ;
  908. X    filesymbol = Flg.flg_s ? Flg.flg_s : FILE_SYMBOL ;
  909. X    flinfo = openfile( fileinfo ) ;
  910. X    (void)fstat( flinfo, &sinfo ) ;
  911. X    if ( !stat( filesymbol, &ssymbol ) &&
  912. X        sinfo.st_mtime < ssymbol.st_mtime )
  913. X        fprintf( stderr,
  914. X           "sps - WARNING: Info file `%s' is older than symbol file `%s'\n",
  915. X            fileinfo, filesymbol ) ;
  916. X# ifdef WARNPASSWD
  917. X    if ( !stat( FILE_PASSWD, &spasswd ) &&
  918. X        sinfo.st_mtime < spasswd.st_mtime )
  919. X        fprintf( stderr,
  920. X           "sps - WARNING: Info file `%s' is older than passwd file `%s'\n",
  921. X            fileinfo, FILE_PASSWD ) ;
  922. X# endif
  923. X    /* Read the information file */
  924. X    if ( read( flinfo, (char*)&Info, sizeof( struct info ) )
  925. X    != sizeof( struct info ) )
  926. X    {
  927. X        fprintf( stderr, "sps - Can't read info file `%s'", fileinfo ) ;
  928. X        sysperror() ;
  929. X    }
  930. X    (void)close( flinfo ) ;
  931. X    /* Find current tty status */
  932. X    ttystatus() ;                   
  933. X    /* Now that we know the available ttys, decode the flags */
  934. X    flagsetup() ;                   
  935. X    process = (struct process*)getcore(Info.i_nproc*sizeof(struct process));
  936. X# ifndef SUNOS40
  937. X    text = (struct text*)getcore( Info.i_ntext * sizeof( struct text ) ) ;
  938. X# endif
  939. X    do
  940. X    {       /* Read current process status */
  941. X# ifdef SUNOS40
  942. X        readstatus( process ) ;
  943. X        /* Select those processes to be listed */
  944. X        plist = needed( process ) ;
  945. X# else
  946. X        readstatus( process, text ) ;
  947. X        /* Select those processes to be listed */
  948. X        plist = needed( process, text ) ;
  949. X# endif
  950. X        /* Form a tree of listed processes */
  951. X        plist = mktree( process, plist ) ;
  952. X        if ( !Flg.flg_N )
  953. X        {       /* Print the processes */
  954. X            prheader() ;
  955. X            printall( plist, 0 ) ;
  956. X        }
  957. X        prsummary() ;
  958. X        (void)fflush( stdout ) ;
  959. X        if ( Flg.flg_r )        
  960. X        {       /* If repeating, again get tty status */
  961. X            ttystatus() ;
  962. X            if ( Flg.flg_rdelay )
  963. X# ifdef BSD42
  964. X                sleep( Flg.flg_rdelay ) ;
  965. X# else
  966. X                sleep( (int)Flg.flg_rdelay ) ;
  967. X# endif
  968. X        }
  969. X    } while ( Flg.flg_r ) ;
  970. X    exit( 0 ) ;
  971. X}
  972. END_OF_FILE
  973.   if test 4246 -ne `wc -c <'main.c'`; then
  974.     echo shar: \"'main.c'\" unpacked with wrong size!
  975.   fi
  976.   # end of 'main.c'
  977. fi
  978. if test -f 'needed.c' -a "${1}" != "-c" ; then 
  979.   echo shar: Will not clobber existing file \"'needed.c'\"
  980. else
  981.   echo shar: Extracting \"'needed.c'\" \(5151 characters\)
  982.   sed "s/^X//" >'needed.c' <<'END_OF_FILE'
  983. X# ifndef lint
  984. Xstatic char SccsId[] =  "@(#)needed.c    1.3\t7/4/90" ;
  985. X# endif
  986. X
  987. X# include       "sps.h"
  988. X# include       "flags.h"
  989. X# ifndef SUNOS40
  990. X# include       <h/text.h>
  991. X# endif
  992. X# include       <stdio.h>
  993. X
  994. X/*
  995. X** NEEDED - Determine which processes are needed for the printout
  996. X** and add these to a list of needed processes.
  997. X*/
  998. X# ifdef SUNOS40
  999. Xstruct process  *needed ( process )
  1000. X
  1001. Xregister struct process         *process ;
  1002. X
  1003. X# else
  1004. X
  1005. Xstruct process  *needed ( process, text )
  1006. X
  1007. Xregister struct process         *process ;
  1008. Xstruct text                     *text ;
  1009. X
  1010. X# endif
  1011. X{
  1012. X    register struct process *p ;
  1013. X    register struct process *plist ;
  1014. X    struct process          *lastp ;
  1015. X    int                     uid ;
  1016. X    extern struct flags     Flg ;
  1017. X    extern union userstate  User ;
  1018. X    extern struct info      Info ;
  1019. X    extern struct ttyline   Notty ;
  1020. X    struct ttyline          *findtty() ;
  1021. X    char                    *getcmd() ;
  1022. X
  1023. X    plist = (struct process*)0 ;
  1024. X    lastp = &process[ Info.i_nproc ] ;
  1025. X    /* Normalise internal pointers from kernel addresses. For each kmem
  1026. X       address in the `proc' and `text' structures, we convert that
  1027. X       address for our own internal use. */
  1028. X    for ( p = process ; p < lastp ; p++ )
  1029. X    {                               
  1030. X        if ( !p->pr_p.p_stat )  
  1031. X            continue ;
  1032. X# ifndef SUNOS40
  1033. X        /* Normalise internal text pointers */
  1034. X        if ( p->pr_p.p_textp )
  1035. X            p->pr_p.p_textp = &text[p->pr_p.p_textp - Info.i_text0];
  1036. X# endif
  1037. X        /* Normalise internal linked list of processes */
  1038. X        p->pr_plink = p->pr_p.p_link ?
  1039. X            &process[ p->pr_p.p_link  - Info.i_proc0 ] :
  1040. X            (struct process*)0 ;
  1041. X        /* Normalise internal parent pointers */
  1042. X        p->pr_pptr = p->pr_p.p_pptr ?
  1043. X            &process[ p->pr_p.p_pptr - Info.i_proc0 ] :
  1044. X            (struct process*)0 ;
  1045. X        /* Check for valid parent pointers */
  1046. X        if ( !p->pr_pptr )
  1047. X        {
  1048. X            p->pr_pptr = process ;
  1049. X            continue ;
  1050. X        }
  1051. X        if ( p->pr_pptr < process || p->pr_pptr >= lastp )
  1052. X        {
  1053. X            fprintf( stderr, "sps - process %d has bad pptr\n",
  1054. X                p->pr_p.p_pid ) ;
  1055. X            p->pr_pptr = process ;
  1056. X        }
  1057. X    }
  1058. X    /* For each process, see if it is a candidate for selection.
  1059. X       If so, retrieve its command arguments and upage information. */
  1060. X    uid = getuid() ;
  1061. X    for ( p = process ; p < lastp ; p++ )
  1062. X    {                               
  1063. X        if ( !p->pr_p.p_stat )
  1064. X            continue ;
  1065. X        /* Count processes and sizes */
  1066. X        summarise( p ) ;
  1067. X        /* Select the given processes. Bear in mind that selection
  1068. X           of processes based on the `F' and `T' flags must be
  1069. X           postponed until the upage is accessed. */
  1070. X        if ( !Flg.flg_F && !Flg.flg_T && !selectproc( p, process, uid ))
  1071. X            continue ;
  1072. X        /* Try to find the process' command arguments. Accessing the
  1073. X           arguments also involves retrieving the upage. */
  1074. X        p->pr_cmd = getcmd( p ) ;
  1075. X        /* If the upage was found successfully, use this information */
  1076. X        if ( p->pr_upag )       
  1077. X        {
  1078. X# ifdef BSD42
  1079. X            p->pr_rself = User.u_us.u_ru ;
  1080. X            p->pr_rchild = User.u_us.u_cru ;
  1081. X# else
  1082. X            p->pr_vself = User.u_us.u_vm ;
  1083. X            p->pr_vchild = User.u_us.u_cvm ;
  1084. X# endif
  1085. X            p->pr_tty = findtty( p ) ;
  1086. X            p->pr_files = filecount( p ) ;
  1087. X        }
  1088. X        else
  1089. X            p->pr_tty = &Notty ;
  1090. X        /* Select on the basis of the `F' and `T' flags */
  1091. X        if ( Flg.flg_F          
  1092. X        && !(p->pr_p.p_pgrp && p->pr_p.p_pgrp == p->pr_tty->l_pgrp) )
  1093. X            continue ;
  1094. X        if ( Flg.flg_T && !selecttty( p ) )
  1095. X            continue ;
  1096. X        /* Arrive here with a selected process. Add this to the
  1097. X           linked list of needed processes. */
  1098. X        p->pr_plink = plist ;   
  1099. X        plist = p ;
  1100. X        p->pr_child = (struct process*)0 ;
  1101. X        p->pr_sibling = (struct process*)0 ;
  1102. X    }
  1103. X    return ( plist ) ;
  1104. X}
  1105. X
  1106. X/* SUMMARISE - Summarises the given process into the `Summary' structure */
  1107. X/*
  1108. X** SHOULD ACCOUNT HERE FOR THE SIZE OF LOADED PAGE TABLES, BUT WE DON'T REALLY
  1109. X** KNOW THEIR RESIDENT SIZES.
  1110. X*/
  1111. Xsummarise ( p )
  1112. X
  1113. Xregister struct process         *p ;
  1114. X
  1115. X{
  1116. X# ifndef SUNOS40
  1117. X    register struct text    *tp ;
  1118. X# endif
  1119. X    int                     busy ;
  1120. X    extern struct summary   Summary ;
  1121. X
  1122. X    Summary.sm_ntotal++ ;
  1123. X    if ( p->pr_p.p_stat == SZOMB )
  1124. X        return ;
  1125. X    /* Firstly, account for processes */
  1126. X# if defined(OLDSTATS) || !defined(SUNOS40)
  1127. X    Summary.sm_ktotal += p->pr_p.p_dsize + p->pr_p.p_ssize ;
  1128. X# else
  1129. X    seg_count( p ) ;        /* count up process pages */
  1130. X    
  1131. X    Summary.sm_ktotal += p->pr_private + p->pr_shared ;
  1132. X# endif
  1133. X    Summary.sm_kloaded += p->pr_p.p_rssize ;
  1134. X    Summary.sm_kswapped += p->pr_p.p_swrss ;
  1135. X    if ( p->pr_p.p_flag & SLOAD )
  1136. X        Summary.sm_nloaded++ ;
  1137. X    else
  1138. X        Summary.sm_nswapped++ ;
  1139. X    busy = (p->pr_p.p_stat == SRUN) || (p->pr_p.p_stat==SSLEEP
  1140. X         && (p->pr_p.p_pri<PZERO && p->pr_p.p_pid > MSPID) ) ;
  1141. X# ifdef SUNOS40
  1142. X    /* Ignore the idle processes */
  1143. X    if ( p->pr_p.p_pid == 3 || p->pr_p.p_pid == 4 )
  1144. X        busy = 0 ;
  1145. X# endif SUNOS40
  1146. X    if ( busy )
  1147. X    {
  1148. X        Summary.sm_nbusy++ ;
  1149. X# if defined(OLDSTATS) || !defined(SUNOS40)
  1150. X        Summary.sm_kbusy += p->pr_p.p_dsize + p->pr_p.p_ssize ;
  1151. X# else
  1152. X        Summary.sm_kbusy += p->pr_private + p->pr_shared ;
  1153. X# endif
  1154. X    }
  1155. X# ifndef SUNOS40
  1156. X    /* Now account for their texts */
  1157. X    if ( !(tp = p->pr_p.p_textp) || !tp->x_count )
  1158. X        return ;                
  1159. X    Summary.sm_ktotal += tp->x_size ;
  1160. X    Summary.sm_kloaded += tp->x_rssize ;
  1161. X    Summary.sm_kswapped += tp->x_swrss ;
  1162. X    if ( busy )
  1163. X        Summary.sm_kbusy += tp->x_size ;
  1164. X    tp->x_count = 0 ;
  1165. X# endif
  1166. X}
  1167. END_OF_FILE
  1168.   if test 5151 -ne `wc -c <'needed.c'`; then
  1169.     echo shar: \"'needed.c'\" unpacked with wrong size!
  1170.   fi
  1171.   # end of 'needed.c'
  1172. fi
  1173. if test -f 'openfiles.c' -a "${1}" != "-c" ; then 
  1174.   echo shar: Will not clobber existing file \"'openfiles.c'\"
  1175. else
  1176.   echo shar: Extracting \"'openfiles.c'\" \(3718 characters\)
  1177.   sed "s/^X//" >'openfiles.c' <<'END_OF_FILE'
  1178. X# ifndef lint
  1179. Xstatic char SccsId[] =  "@(#)openfiles.c    1.1\t10/1/88" ;
  1180. X# endif
  1181. X
  1182. X# include       <stdio.h>
  1183. X# include       "sps.h"
  1184. X# include       "flags.h"
  1185. X# include       <varargs.h>
  1186. X# ifdef KVM
  1187. X# include       <kvm.h>
  1188. X# endif
  1189. X
  1190. X/* Miscellaneous procedures */
  1191. X
  1192. X/* OPENFILE - Opens the named file */
  1193. Xopenfile ( name )
  1194. X
  1195. Xchar                            *name ;
  1196. X
  1197. X{
  1198. X    register int            fd ;
  1199. X
  1200. X    if ( (fd = open( name, 0 )) >= 0 )
  1201. X        return ( fd ) ;
  1202. X    fprintf( stderr, "sps - Can't open %s", name ) ;
  1203. X    sysperror() ;
  1204. X    /* NOTREACHED */
  1205. X}
  1206. X
  1207. X# ifdef KVM
  1208. X
  1209. Xgetkmem ( addr, buf, bufsize )
  1210. X
  1211. Xlong                            addr ;
  1212. Xchar                            *buf ;
  1213. Xint                             bufsize ;
  1214. X{
  1215. X    extern kvm_t            *Flkvm ;
  1216. X
  1217. X    return( kvm_read( Flkvm, (long)addr, buf, bufsize ) ) ;
  1218. X}
  1219. X
  1220. X# else
  1221. X
  1222. Xgetkmem ( addr, buf, bufsize )
  1223. X
  1224. Xlong                            addr ;
  1225. Xchar                            *buf ;
  1226. Xint                             bufsize ;
  1227. X{
  1228. X    extern int              Flkmem ;
  1229. X
  1230. X    memseek( Flkmem, (long)addr ) ;
  1231. X    return( read( Flkmem, buf, bufsize ) ) ;
  1232. X}
  1233. X
  1234. X/* MEMSEEK - Seek on a special file */
  1235. Xmemseek ( fd, pos )
  1236. X
  1237. Xint                             fd ;
  1238. Xlong                            pos ;
  1239. X
  1240. X{
  1241. X    extern int              errno ;
  1242. X    extern struct flags     Flg ;
  1243. X    long                    lseek() ;
  1244. X
  1245. X    errno = 0 ;
  1246. X    if ( Flg.flg_k )
  1247. X# ifdef SUN
  1248. X        pos &= KERNELBASE - 1 ;
  1249. X# else
  1250. X        pos &= 0x7fffffff ;
  1251. X# endif
  1252. X    (void)lseek( fd, pos, 0 ) ;
  1253. X    if ( errno )
  1254. X    {
  1255. X        fprintf( stderr, "sps - Seek failed" ) ;
  1256. X        sysperror() ;
  1257. X    }
  1258. X}
  1259. X
  1260. X/* SWSEEK - Seek on the swap device */
  1261. Xswseek ( pos )
  1262. X
  1263. Xlong                            pos ;
  1264. X
  1265. X{
  1266. X    extern int              Flswap ;
  1267. X    extern int              errno ;
  1268. X    long                    lseek() ;
  1269. X
  1270. X    errno = 0 ;
  1271. X    (void)lseek( Flswap, pos, 0 ) ;
  1272. X    if ( errno )
  1273. X    {
  1274. X        fprintf( stderr, "sps - Seek failed" ) ;
  1275. X        sysperror() ;
  1276. X    }
  1277. X}
  1278. X
  1279. X# endif
  1280. X
  1281. X# ifdef lint
  1282. Xint                             errno ;
  1283. Xint                             sys_nerr ;
  1284. Xchar                            *sys_errlist[] ;
  1285. X# endif
  1286. X
  1287. X/* SYSPERROR - Reports a system defined error msg and then exits gracefully */
  1288. Xsysperror ()
  1289. X{
  1290. X    extern int              errno ;
  1291. X    extern int              sys_nerr ;
  1292. X    extern char             *sys_errlist[] ;
  1293. X
  1294. X    if ( 0 < errno && errno < sys_nerr )
  1295. X        fprintf( stderr, " : %s", sys_errlist[errno] ) ;
  1296. X    (void)fputc( '\n', stderr ) ;
  1297. X    exit( 1 ) ;
  1298. X}
  1299. X
  1300. X/* STRSAVE - Store a string in core for later use. */
  1301. Xchar    *strsave ( cp )
  1302. X
  1303. Xregister char                   *cp ;
  1304. X
  1305. X{
  1306. X    register char           *chp ;
  1307. X    char                    *getcore(), *strcpy() ;
  1308. X
  1309. X    chp = getcore( strlen( cp ) + 1 ) ;
  1310. X    (void)strcpy( chp, cp ) ;
  1311. X    return ( chp ) ;
  1312. X}
  1313. X
  1314. X/* GETCORE - Allocate and return a pointer to the asked for amount of core */
  1315. Xchar    *getcore ( size )
  1316. X
  1317. Xregister int                    size ;
  1318. X
  1319. X{
  1320. X    register char           *chp ;
  1321. X    char                    *malloc() ;
  1322. X
  1323. X    if ( chp = malloc( (unsigned)size ) )
  1324. X        return ( chp ) ;
  1325. X    fprintf( stderr, "sps - Out of core" ) ;
  1326. X    sysperror() ;
  1327. X    /* NOTREACHED */
  1328. X}
  1329. X
  1330. Xunion flaglist  *getflgsp ( argc )
  1331. X
  1332. Xregister int                    argc ;
  1333. X
  1334. X{
  1335. X    char                    *getcore() ;
  1336. X
  1337. X    return ( (union flaglist*)getcore( sizeof( union flaglist )*argc ) ) ;
  1338. X}
  1339. X
  1340. X/* PREXIT - Print an error message and exit */
  1341. X/* VARARGS */
  1342. X/* ARGSUSED */
  1343. Xprexit ( va_alist )
  1344. X
  1345. Xva_dcl
  1346. X
  1347. X{
  1348. X    char                    *fmt ;
  1349. X    va_list                  args ;
  1350. X
  1351. X    va_start( args ) ;
  1352. X    fmt = va_arg( args, char * ) ;
  1353. X
  1354. X    vfprintf( stderr, fmt, args ) ;
  1355. X    exit( 1 ) ;
  1356. X}
  1357. X
  1358. X# ifndef VPRINTF
  1359. X
  1360. Xint vfprintf ( filep, fmt, args )
  1361. X
  1362. XFILE                            *filep ;
  1363. Xchar                            *fmt ;
  1364. Xva_list                          args ;
  1365. X
  1366. X{
  1367. X    _doprnt( fmt, args, filep ) ;    
  1368. X    return( ferror( filep ) ? EOF : 0 ) ;
  1369. X}
  1370. X
  1371. X# endif
  1372. END_OF_FILE
  1373.   if test 3718 -ne `wc -c <'openfiles.c'`; then
  1374.     echo shar: \"'openfiles.c'\" unpacked with wrong size!
  1375.   fi
  1376.   # end of 'openfiles.c'
  1377. fi
  1378. if test -f 'sps.h' -a "${1}" != "-c" ; then 
  1379.   echo shar: Will not clobber existing file \"'sps.h'\"
  1380. else
  1381.   echo shar: Extracting \"'sps.h'\" \(6824 characters\)
  1382.   sed "s/^X//" >'sps.h' <<'END_OF_FILE'
  1383. X# ifndef lint
  1384. Xstatic char SpsHId[] =  "@(#)sps.h    1.3\t7/4/90" ;
  1385. X# endif
  1386. X
  1387. X# ifdef SUNOS40
  1388. X#  define KERNEL
  1389. X# endif SUNOS40
  1390. X# include    <h/param.h>
  1391. X# undef KERNEL
  1392. X# include    <h/dir.h>
  1393. X# include    <h/user.h>
  1394. X# include    <h/proc.h>
  1395. X
  1396. X# ifdef SUNOS40
  1397. X#  ifndef BSD43
  1398. X#   define BSD43
  1399. X# endif BSD43
  1400. X# endif SUNOS40
  1401. X
  1402. X/*
  1403. X** Maximum # of users to be considered. (Because user names are stored
  1404. X** in a hash table, this should probably be at least double the number
  1405. X** of actual users defined in /etc/passwd or by the Yellow Pages.)
  1406. X*/
  1407. X# define    MAXUSERS    100
  1408. X/* Maximum # ttys to be considered, plus 1 for the console ... */
  1409. X# define    MAXTTYS        97
  1410. X
  1411. X
  1412. X/* Maximum user name length ... */
  1413. X# define    UNAMELEN    8
  1414. X/* Maximum process-id not to be considered busy ... */
  1415. X# define    MSPID        2
  1416. X/* # of wait states defined in the `struct info' ... */
  1417. X# ifdef NFS
  1418. X#  ifdef SUN
  1419. X#   define    NWAITSTATE    16
  1420. X#  else
  1421. X#   define    NWAITSTATE    36
  1422. X#  endif SUN
  1423. X# else NFS
  1424. X#  ifdef ULTRIX20
  1425. X#   define    NWAITSTATE    36
  1426. X#  else ULTRIX20
  1427. X#   define    NWAITSTATE    35
  1428. X#  endif ULTRIX20
  1429. X# endif NFS
  1430. X
  1431. X/* Convert clicks to kbytes ... */
  1432. X# ifndef PGSHIFT
  1433. X#  define    KBYTES( size )    ((size) << 1)
  1434. X# else PGSHIFT
  1435. X#  if PGSHIFT > 10
  1436. X#   define        KBYTES( size )  ((size) << (PGSHIFT - 10))
  1437. X#  else
  1438. X#   define    KBYTES( size )    ((size) >> (10 - PGSHIFT))
  1439. X#  endif
  1440. X# endif PGSHIFT
  1441. X
  1442. X/* Standard files to be examined ... */
  1443. X# define    FILE_MEM    "/dev/mem"    /* System physical memory */
  1444. X# define    FILE_KMEM    "/dev/kmem"    /* Kernel virtual memory */
  1445. X# define    FILE_SWAP    "/dev/drum"    /* Swap/paging device */
  1446. X# define    FILE_DEV    "/dev"        /* Directory of tty entries */
  1447. X# define    FILE_SYMBOL    "/vmunix"    /* Symbol file for nlist() */
  1448. X# define    FILE_INFO    "/tmp/.spsinfo"    /* Sps information file */
  1449. X# define    FILE_PASSWD    "/etc/passwd"    /* User database */
  1450. X
  1451. X/* Structure to hold necessary information concerning a tty ... */
  1452. Xstruct ttyline
  1453. X{
  1454. X    char            l_name[2] ;    /* Tty character name */
  1455. X    unsigned short        l_pgrp ;    /* Tty process group */
  1456. X# ifdef SUNOS40
  1457. X    struct streamtab    *l_addr ;    /* Ptr to streamtab in kmem */
  1458. X    struct stdata        *l_stdata ;    /* Ptr to stdata at runtime */
  1459. X# else SUNOS40
  1460. X    struct tty        *l_addr ;    /* Ptr to tty struct in kmem */
  1461. X# endif SUNOS40
  1462. X    dev_t            l_dev ;        /* Tty device # */
  1463. X} ;
  1464. X
  1465. X/* Structure holding a single hash table entry ... */
  1466. Xstruct hashtab
  1467. X{
  1468. X    short            h_uid ;        /* Uid of user entry */
  1469. X    char            h_uname[ UNAMELEN ] ; /* Corresponding name */
  1470. X} ;
  1471. X
  1472. X/*
  1473. X** Format of the standard information file maintained by sps.
  1474. X** This structure is filled in at initialisation time and then is read back
  1475. X** in whenever sps is invoked.
  1476. X** Note that the pointer variables in this structure refer to
  1477. X** kernel virtual addresses, not addresses within sps.
  1478. X** These variable are typed as such so that pointer arithmetic
  1479. X** on the kernel addresses will work correctly.
  1480. X*/
  1481. Xstruct info
  1482. X{    /* Kernel values determining process, tty and upage info ... */
  1483. X    struct proc        *i_proc0 ;    /* address of process table */
  1484. X    int            i_nproc ;    /* length of process table */
  1485. X# ifndef SUNOS40
  1486. X    struct text        *i_text0 ;    /* address of text table */
  1487. X# endif SUNOS40
  1488. X    int            i_ntext ;    /* length of text table */
  1489. X# ifdef ULTRIX20
  1490. X    struct gnode        *i_inode0 ;    /* address of inode table */
  1491. X# else ULTRIX20
  1492. X    struct inode        *i_inode0 ;    /* address of inode table */
  1493. X# endif ULTRIX20
  1494. X    int            i_ninode ;    /* length of inode table */
  1495. X    int            i_ecmx ;    /* max physical memory address*/
  1496. X# ifndef SUNOS40
  1497. X    struct buf        *i_swbuf0 ;    /* address of swap buffers */
  1498. X    int            i_nswbuf ;    /* # swap buffers */
  1499. X    struct buf        *i_buf0 ;    /* address of i/o buffers */
  1500. X    int            i_nbuf ;    /* # i/o buffers */
  1501. X    struct pte        *i_usrptmap ;    /* page table map */
  1502. X    struct pte        *i_usrpt ;    /* page table map */
  1503. X# endif SUNOS40
  1504. X    struct cdevsw        *i_cdevsw ;    /* device switch to find ttys */
  1505. X# ifdef BSD42
  1506. X#  ifdef NFS
  1507. X    struct dquot        *i_quota0 ;    /* disc quota structures */
  1508. X#  else NFS
  1509. X    struct quota        *i_quota0 ;    /* disc quota structures */
  1510. X#  endif NFS
  1511. X    int            i_nquota ;    /* # quota structures */
  1512. X    int            i_dmmin ;    /* The start of the disc map */
  1513. X    int            i_dmmax ;    /* The end of the disc map */
  1514. X    struct mbuf        *i_mbutl ;    /* Start of mbuf area */
  1515. X# else BSD42
  1516. X    int            i_hz ;        /* Clock rate */
  1517. X# endif BSD42
  1518. X# ifdef CHAOS
  1519. X    caddr_t            i_Chconntab ;    /* Chaos connection table */
  1520. X# endif
  1521. X    /* Kernel addresses are associated with process wait states ... */
  1522. X    caddr_t            i_waitstate[ NWAITSTATE ] ;
  1523. X    /* User names, stored in a hash table ... */
  1524. X    struct hashtab        i_hnames[ MAXUSERS ] ;
  1525. X    /* Tty device info ... */
  1526. X    struct ttyline        i_ttyline[ MAXTTYS ] ;
  1527. X# ifdef SUNOS40
  1528. X    struct seg_ops        *i_segvn_ops ;    /* ptr to vnode segment ops */
  1529. X    struct pty        *i_ptybase ;
  1530. X    int            i_npty ;
  1531. X#  ifdef SUNOS41
  1532. X    struct strstat        *i_strst;
  1533. X    struct stdata        *i_allstream;
  1534. X#  else SUNOS41
  1535. X    struct stdata        *i_streams ;    /* streams list */
  1536. X    struct stdata        *i_streamsNSTREAMS ;
  1537. X#  endif SUNOS41
  1538. X    caddr_t            i_sysbase ;
  1539. X# endif SUNOS40
  1540. X} ;
  1541. X
  1542. X/*
  1543. X** The symbol structure cross-references values read from the kernel with
  1544. X** their place in the info structure, and if such a value is associated with
  1545. X** a process wait state or not.
  1546. X*/
  1547. Xstruct symbol
  1548. X{
  1549. X    char            *s_kname ;    /* Kernel symbol name */
  1550. X    char            s_indirect ;    /* Value requires indirection */
  1551. X    caddr_t            *s_info ;    /* Corresponding info address */
  1552. X    char            *s_wait ;    /* Reason for wait, if any */
  1553. X} ;
  1554. X
  1555. X/* The `user' structure obtained from /dev/mem or /dev/swap ... */
  1556. Xunion userstate
  1557. X{
  1558. X    struct user        u_us ;
  1559. X    char            u_pg[ UPAGES ][ NBPG ] ;
  1560. X} ;
  1561. X
  1562. X/* Information concerning each process filled from /dev/kmem ... */
  1563. Xstruct process
  1564. X{
  1565. X    struct proc        pr_p ;        /* struct proc from /dev/kmem */
  1566. X    struct process        *pr_plink ;    /* Normalised ptrs from above */
  1567. X    struct process        *pr_sibling ;    /* Ptr to sibling process */
  1568. X    struct process        *pr_child ;    /* Ptr to child process */
  1569. X    struct process        *pr_pptr ;    /* Ptr to parent process */
  1570. X# ifdef BSD42
  1571. X    struct rusage        pr_rself ;    /* Read from upage for self */
  1572. X    struct rusage        pr_rchild ;    /* ... and the children */
  1573. X# else BSD42
  1574. X    struct vtimes        pr_vself ;    /* Read from upage for self */
  1575. X    struct vtimes        pr_vchild ;    /* ... and the children */
  1576. X# endif BSD42
  1577. X    int            pr_files ;    /* # open files */
  1578. X    struct ttyline        *pr_tty ;    /* Associated tty information */
  1579. X    char            *pr_cmd ;    /* Command args, from upage */
  1580. X    int            pr_upag:1 ;    /* Upage was obtained */
  1581. X    int            pr_csaved:1 ;    /* Cmd args saved by malloc() */
  1582. X# ifdef SUNOS40
  1583. X    unsigned        pr_private ;    /* private pages */
  1584. X    unsigned        pr_shared ;    /* shared pages */
  1585. X# endif SUNOS40
  1586. X} ;
  1587. X
  1588. X/* Structure to hold summarising information ... */
  1589. Xstruct summary
  1590. X{
  1591. X    long            sm_ntotal ;    /* Total # processes */
  1592. X    long            sm_ktotal ;    /* Total virtual memory */
  1593. X    long            sm_nbusy ;    /* # busy processes */
  1594. X    long            sm_kbusy ;    /* Busy virtual memory */
  1595. X    long            sm_nloaded ;    /* # loaded processes */
  1596. X    long            sm_kloaded ;    /* Active resident memory */
  1597. X    long            sm_nswapped ;    /* # swapped processes */
  1598. X    long            sm_kswapped ;    /* Size totally swapped out */
  1599. X} ;
  1600. END_OF_FILE
  1601.   if test 6824 -ne `wc -c <'sps.h'`; then
  1602.     echo shar: \"'sps.h'\" unpacked with wrong size!
  1603.   fi
  1604.   # end of 'sps.h'
  1605. fi
  1606. if test -f 'stream.c' -a "${1}" != "-c" ; then 
  1607.   echo shar: Will not clobber existing file \"'stream.c'\"
  1608. else
  1609.   echo shar: Extracting \"'stream.c'\" \(5425 characters\)
  1610.   sed "s/^X//" >'stream.c' <<'END_OF_FILE'
  1611. X# ifndef lint
  1612. Xstatic char SccsId[] =  "@(#)stream.c    1.2\t7/4/90" ;
  1613. X# endif
  1614. X
  1615. X# ifdef SUNOS40
  1616. X#  include        "sps.h"
  1617. X#  include        <h/stream.h>
  1618. X#  include        <h/vnode.h>
  1619. X#  ifdef SUNOS41
  1620. X#   include        <h/strstat.h>
  1621. X#  endif
  1622. X
  1623. Xstatic struct stdata    *pstreams ;
  1624. Xstatic struct stdata    *pstreamsNSTREAMS ;
  1625. X
  1626. Xinit_streams_tab()
  1627. X{
  1628. X    int            len ;
  1629. X    extern struct info    Info ;
  1630. X    register struct stdata    *s ;
  1631. X    struct vnode        *v ;
  1632. X    char            *getcore() ;
  1633. X
  1634. X    if ( pstreams )
  1635. X        /* reinitializing */
  1636. X        for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
  1637. X            if ( s->sd_vnode != 0 )
  1638. X                free( (char*)s->sd_vnode ) ;
  1639. X        free( (char*)pstreams ) ;
  1640. X#  ifdef SUNOS41
  1641. X    /*
  1642. X     * In SunOS 4.1, the stream heads are in a linked list.  A
  1643. X     * `struct strstat' contains the number of active streams; the
  1644. X     * variable `allstream' points to an apparently random
  1645. X     * position in a doubly linked `struct stdata' chain.
  1646. X     *
  1647. X     * To find all streams we'll have to scan the chain forwards
  1648. X     * AND backwards from `allstream'.  `int going_forwards' below
  1649. X     * tells which direction we are currently going.  Weird.
  1650. X     *
  1651. X     */
  1652. X
  1653. X    {
  1654. X        struct strstat        strst ;
  1655. X        int            n ;
  1656. X        long            addr ;
  1657. X        struct stdata        *this_stream ;
  1658. X        int            going_forwards = 1 ;
  1659. X    
  1660. X        if ( getkmem ((long) Info.i_strst, (char *) &strst,
  1661. X            sizeof ( struct strstat )) != sizeof ( struct strstat ))
  1662. X            return 0 ;
  1663. X        len = strst.stream.use * sizeof( struct stdata ) ;
  1664. X        pstreams = (struct stdata *)getcore (len ) ;
  1665. X        addr = (long)Info.i_allstream ;
  1666. X        this_stream = pstreams ;
  1667. X        pstreamsNSTREAMS = pstreams - 1 ;
  1668. X        for (n = 0 ; n < strst.stream.use ; n++)
  1669. X        {
  1670. X            if ( getkmem ( addr, (char *) this_stream,
  1671. X                sizeof ( struct stdata ))
  1672. X                != sizeof ( struct stdata ))
  1673. X            {
  1674. X                /*
  1675. X                 * If we are following the `sd_next' chain we'll
  1676. X                 * have to start over from the stream pointed to
  1677. X                 * by Info.i_allstream and scan `sd_prev'
  1678. X                 * backwards.
  1679. X                 */
  1680. X                if ( going_forwards && n > 0 )
  1681. X                {
  1682. X                    going_forwards = 0 ;
  1683. X                    addr = (long) pstreams[0].sd_prev ;
  1684. X                    n--;
  1685. X                    continue ;
  1686. X                }
  1687. X                if ( pstreamsNSTREAMS < pstreams )
  1688. X                    return 0 ;
  1689. X                break ;
  1690. X            }
  1691. X            addr = going_forwards ? (long) this_stream->sd_next :
  1692. X                (long) this_stream->sd_prev ;
  1693. X            this_stream++ ;
  1694. X            pstreamsNSTREAMS++ ;
  1695. X        }
  1696. X    }
  1697. X#  else SUNOS41
  1698. X    len = ((Info.i_streamsNSTREAMS - Info.i_streams) + 1)
  1699. X        * sizeof( struct stdata ) ;
  1700. X    pstreams = (struct stdata *)getcore( len ) ;
  1701. X    pstreamsNSTREAMS = pstreams + (len / sizeof( struct stdata ) ) ;
  1702. X    if ( getkmem( (long)Info.i_streams, (char *)pstreams, len ) != len )
  1703. X        return( 0 ) ;
  1704. X#  endif SUNOS41
  1705. X
  1706. X    for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
  1707. X        if ( s->sd_vnode != 0 )
  1708. X        {
  1709. X            if ( ( v = (struct vnode*)getcore( sizeof( *v ) ) )
  1710. X            && getkmem( (long)s->sd_vnode, (char*)v, sizeof( *v ) )
  1711. X            == sizeof( *v ) )
  1712. X            {
  1713. X                s->sd_vnode = v ;
  1714. X                continue ;
  1715. X            }
  1716. X
  1717. X            s->sd_vnode = 0 ;
  1718. X        }
  1719. X    return( 1 ) ;
  1720. X}
  1721. X
  1722. X
  1723. X#  ifdef SUNOS41
  1724. Xstruct sess *find_session ( addr )
  1725. X
  1726. Xstruct sess            *addr ;
  1727. X
  1728. X{
  1729. X    /*
  1730. X     * SunOS 4.1 seems to store controlling tty's in a "struct
  1731. X     * sess" which is accessible as p->p_sessp.  Another layer
  1732. X     * of indirection to wade through...
  1733. X     *
  1734. X     * To make this a tiny bit faster, I'll store sessions in a
  1735. X     * linked list as I read them in with getkmem; subsequent
  1736. X     * calls to find_session() check the cache.
  1737. X     */
  1738. X
  1739. X    struct sps_sess {
  1740. X        struct sess        sess ;
  1741. X        struct sess        *addr ;
  1742. X        struct sps_sess        *next ;
  1743. X    };
  1744. X
  1745. X    static struct sps_sess        *sessions ; /* Cache of known sessions*/
  1746. X    register struct sps_sess    *s ;
  1747. X
  1748. X    /* Try to find the session in the cache */
  1749. X    for ( s = sessions ; s ; s = s->next )
  1750. X        if ( s->addr == addr )
  1751. X            return &s->sess ;
  1752. X    /* Not found; get it from kmem and put it in the cache */
  1753. X    s = (struct sps_sess *)getcore( sizeof ( struct sps_sess ) ) ;
  1754. X    if ( getkmem ((long) addr, (char *) &s->sess,
  1755. X            sizeof ( struct sess )) != sizeof ( struct sess ) )
  1756. X        return 0 ;
  1757. X    s->addr = addr ;
  1758. X    s->next = sessions ;
  1759. X    sessions = s ;
  1760. X    return &s->sess ;
  1761. X}
  1762. X#  endif SUNOS41
  1763. X
  1764. Xstruct stdata *getstdata ( st, dev )
  1765. X
  1766. Xstruct streamtab                *st ;
  1767. Xdev_t                            dev ;
  1768. X
  1769. X{
  1770. X    register struct stdata  *s ;
  1771. X
  1772. X    for ( s = pstreams ; s <= pstreamsNSTREAMS ; s++ )
  1773. X        if ( s->sd_strtab == st && s->sd_vnode
  1774. X        && s->sd_vnode->v_rdev == dev )
  1775. X            return( s ) ;
  1776. X    return( 0 ) ;
  1777. X}
  1778. X
  1779. X/* 1 if `w' is in the address range defined by `a1' and `a2' ... */
  1780. X# define        INRANGE( w, a1, a2 ) \
  1781. X            ( (caddr_t)(a1) <= (w) && (w) < (caddr_t)(a2) )
  1782. X
  1783. Xchar *gettty ( lp, w )
  1784. X
  1785. Xregister struct ttyline         *lp ;
  1786. Xcaddr_t                         w ;
  1787. X
  1788. X{
  1789. X    struct stdata           *s ;
  1790. X    struct queue            *q ;
  1791. X    struct queue            qq[2] ;
  1792. X    char                    *cp = 0 ;
  1793. X
  1794. X    if ( ( s = lp->l_stdata ) == 0 )
  1795. X        return( 0 ) ;
  1796. X
  1797. X    q = s->sd_wrq ;        /* get write queue (only queue_t in stdata) */
  1798. X    do
  1799. X    {
  1800. X        if ( INRANGE( w, RD( q ), q ) )
  1801. X        {            /* check read queue */
  1802. X            cp = "rtty??" ;
  1803. X            break ;
  1804. X        }
  1805. X        if ( INRANGE( w, q, WR ( q ) ) )
  1806. X        {            /* check write queue */
  1807. X            cp = "wtty??" ;
  1808. X            break ;
  1809. X        }
  1810. X        /* check queue private data structures - useful??? */
  1811. X        if ( getkmem( (long)RD( q ), (char*)qq, sizeof( qq ) )
  1812. X        != sizeof( qq ) )
  1813. X            break ;
  1814. X        if ( INRANGE( w, qq[0].q_ptr, qq[0].q_ptr + 1 ) )
  1815. X        {
  1816. X            cp = "r?ty??" ;
  1817. X        }
  1818. X        if ( INRANGE( w, qq[1].q_ptr, qq[1].q_ptr + 1 ) )
  1819. X        {
  1820. X            cp = "w?ty??" ;
  1821. X        }
  1822. X        q = qq[1].q_next ;
  1823. X    }
  1824. X    while ( q ) ;
  1825. X    if ( cp )
  1826. X    {
  1827. X        cp[4] = lp->l_name[0] ;
  1828. X        cp[5] = lp->l_name[1] ;
  1829. X        return( cp ) ;
  1830. X    }
  1831. X    return( 0 ) ;            /* chain down list? */
  1832. X}
  1833. X# endif SUNOS40
  1834. X
  1835. END_OF_FILE
  1836.   if test 5425 -ne `wc -c <'stream.c'`; then
  1837.     echo shar: \"'stream.c'\" unpacked with wrong size!
  1838.   fi
  1839.   # end of 'stream.c'
  1840. fi
  1841. echo shar: End of archive 2 \(of 4\).
  1842. cp /dev/null ark2isdone
  1843. MISSING=""
  1844. for I in 1 2 3 4 ; do
  1845.     if test ! -f ark${I}isdone ; then
  1846.     MISSING="${MISSING} ${I}"
  1847.     fi
  1848. done
  1849. if test "${MISSING}" = "" ; then
  1850.     echo You have unpacked all 4 archives.
  1851.     rm -f ark[1-9]isdone
  1852. else
  1853.     echo You still must unpack the following archives:
  1854.     echo "        " ${MISSING}
  1855. fi
  1856. exit 0
  1857. exit 0 # Just in case...
  1858.